/*
 * $RCSfile: ObjectUtil.java,v $
 * $Revision: 1.5 $
 *
 * Comments:
 *
 * (C) Copyright Biuro-Technika 2009.  All rights reserved.
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Biuro-Technika
 * The copyright notice above does not evidence any
 * actual or intended publication of such source code.
 *
 * $Author: michal $          $Locker:  $
 * $Date: 2010/06/12 20:43:30 $
 * $Log: ObjectUtil.java,v $
 * Revision 1.5  2010/06/12 20:43:30  michal
 * parametryzacja kodu,optymalizacja petli
 *
 * Revision 1.4  2010/06/02 14:12:02  michal
 * poprawa w parametrach
 *
 * Revision 1.3  2010/06/02 12:53:51  michal
 * parametryzacja kodu
 *
 * Revision 1.2  2010/02/25 13:22:24  michal
 * poprawa nazewnictwa metod, wylaczenie domyslnego sortowania
 *
 * Revision 1.1  2010/01/25 13:06:18  michal
 * original source code
 *
 */

package parasoft.centrap.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ObjectUtil {
	public static ObjectUtil newInstance(){
		return new ObjectUtil();
	}
	
	/**
	 * Przeksztalca liste obiektow na tablice obiektow
	 * @return tablica obiektow
	 */
	public static <T> Object[] getArray(List<T> in){
		return getArray( in , false);
	}
	
	/**
	 * Przeksztalca liste obiektow na tablice obiektow
	 * @param <T>
	 *
	 * @param in lista obiektow
	 * @param sort czy sortowac elementy
	 *
	 * @return tablica obiektow
	 */
	public static <T> Object[] getArray(List<T> in, boolean sort){
		Object[] out = null;
		if(in!=null){
			if(in.size()>0){
				out = in.toArray();
				if(sort){
					Arrays.sort(out);
				}
			}else{
				out = new ArrayList<T>().toArray();
			}
		}
		return out;
	}

	/**
	 * Przeksztalca liste ciagow znakowych na tablice ciagow znakowych
	 *
	 * @param in lista ciagow znakowych
	 * @param sort czy sortowac elementy
	 * @param tools narzedzie
	 *
	 * @return tablica ciagow znakowych
	 * @see parasoft.centrap.utils.Tool
	 */
	public static <T,P> Object[] getArray(List<P> in, boolean sort, Tool<T,P> tools){
		return getArray( in,  sort, asList(tools));
	}
	/**
	 * Przeksztalca liste obiektow na tablice obiektow
	 *
	 * @param in lista obiektow
	 * @param tools narzedzie
	 *
	 * @return tablica obiektor
	 * @see parasoft.centrap.utils.Tool
	 */
	public static <T,P> Object[] getArray(List<P> in, Tool<T,P> tools){
		return getArray( in , false ,asList(tools));
	}
	/**
	 * Przeksztalca liste obiektow na tablice obiektow
	 *
	 * @param in lista obiektow
	 * @param tools tablica narzedzi
	 *
	 * @return tablica obiektow
	 * @see parasoft.centrap.utils.Tool
	 */
	public static <T,P> Object[] getArray(List<P> in, List<Tool<T,P>> tools){
		return getArray( in , false ,tools);
	}
	/**
	 * Przeksztalca liste obiektow na tablice obiektow.</br>
	 * Przy sortowaniu wymagana implementacja equals oraz compareTo.
	 *
	 * @param in lista obiektow
	 * @param tools narzedzie
	 * @param sort czy sortowac elementy
	 *
	 * @return tablica obiektow
	 * @see parasoft.centrap.utils.Tool
	 * @see java.lang.Comparable
	 */
	public static <T,P> Object[] getArray(List<P> in, Tool<T,P> tools , boolean sort){
		return  getArray( in, asList(tools), sort);
	}
	/**
	 * Przeksztalca liste obiektow na tablice obiektow.</br>
	 * Przy sortowaniu wymagana implementacja equals oraz compareTo.
	 *
	 * @param in lista obiektow
	 * @param sort czy sortowac elementy
	 * @param tools tablica narzedzi
	 *
	 * @return tablica obiektow
	 * @see parasoft.centrap.utils.Tool
	 * @see java.lang.Comparable
	 */
	@SuppressWarnings("unchecked")
	public static <T,P> Object[] getArray(List<P> in, boolean sort, List<Tool<T,P>> tools){
		Object[] out = null;
		if(in!=null){
			if(in.size()>0){
				out = new Object[in.size()];
				out = in.toArray(out);
				if(sort){
					Arrays.sort(out);
				}
				for(int i = 0, len = out.length ;i <len; i++){
					out[i] = (invoke((P)out[i],tools,i));
				}
			}else{
				out = new ArrayList<T>().toArray();
			}
		}
		return out;
	}
	/**
	 * Przeksztalca liste obiektow na tablice obiektow.</br>
	 * Przy sortowaniu wymagana implementacja equals oraz compareTo.
	 * @param in lista obiektow
	 * @param tools tablica narzedzi
	 * @param sort czy sortowac elementy
	 *
	 * @return tablica obiektow
	 * @see parasoft.centrap.utils.Tool
	 * @see java.lang.Comparable
	 */
	protected static <T,P> Object[] getArray(List<P> in, List<Tool<T,P>> tools , boolean sort){
		int len = in.size();
		Object[] out = new Object[len];
		if(in!=null && len>0){
			for(int i = 0 ;i <len; i++){
				Object cout = (invoke(in.get(i),tools, i)); 
				out[i] = cout;
			}
			if(sort){
				Arrays.sort(out);
			}
		}
		return out;
	}
	/**
	 * Przetwarza obiekt in zgodnie z narzedziami podanymi w tablicy tools.<br />
	 * Numer elementu ustawiony na 0
	 *
	 * @param in obiekt wejsciowy
	 * @param tools narzedzie
	 *
	 * @return przetworzony obiekt
	 * @see parasoft.centrap.utils.Tool
	 * @see parasoft.centrap.utils.ObjectUtil#invoke(Object, Tool, int)
	 */
	public static <T,P> T invoke(P in, Tool<T,P> tools){
		return invoke(in, asList(tools));
	}

	/**
	 * Przetwarza obiekt in zgodnie z narzedziami podanymi w tablicy tools.<br />
	 * Numer elementu ustawiony na 0
	 *
	 * @param in obiekt wejsciowy
	 * @param tools tablica narzedzi
	 *
	 * @return przetworzony obiekt
	 * @see parasoft.centrap.utils.Tool
	 */
	public static <T,P> T invoke(P in, List<Tool<T,P>> tools){
		return invoke(in, tools, 0);
	}

	/**
	 * Przetwarza obiekt in zgodnie z narzedziami podanymi w tablicy tools.<br />
	 * Mozliwosc ustawienia numeru elementu
	 *
	 * @param in obiekt wejsciowy
	 * @param tools tablica narzedzi
	 * @param x numer elementu
	 *
	 * @return przetworzony obiekt
	 * @see parasoft.centrap.utils.Tool
	 */
	protected static <T,P> T invoke(P in, List<Tool<T,P>> tools, int x){
		T out = (T) null;
		if(in!=null && tools != null && tools.size() > 0){
			out = (T) in;
			for(int i = 0, len = tools.size() ;i < len;i++){
				if(tools.get(i)==null){
					continue;
				}
				tools.get(i).setNr(x);
				out = tools.get(i).invoke((P) out);
			}
		}
		return out;
	}
	/**
	 * Przetwarza obiekt in zgodnie z narzedziami podanymi w tablicy tools.<br />
	 * Mozliwosc ustawienia numeru elementu
	 *
	 * @param in obiekt wejsciowy
	 * @param tools tablica narzedzi
	 * @param x numer elementu
	 *
	 * @return przetworzony obiekt
	 * @see parasoft.centrap.utils.Tool
	 */
	protected static <T,P> List<T> invoke(List<P> ins, List<Tool<T,P>> tools, int x){
		List<T> out = new ArrayList<T>();
		if(ins!=null && tools != null && tools.size() > 0){
			for(P in : ins){
				T t = (T) null;
				for(int i = 0, len = tools.size() ;i < len;i++){
					if(tools.get(i)==null){
						continue;
					}
					tools.get(i).setNr(x);
					t = tools.get(i).invoke(in);
				}
				out.add(t);
			}
		}
		return out;
	}
	
	public static <T> List<T> asList(T... objs){
		List<T> out = new ArrayList<T>();
		if(objs!=null){
			for (T obj : objs) {
				out.add(obj);
			}
		}
		return out;
	}
}
